<script setup>
import MwTable from "./component/MwTableCamera";
import MwTableLog from "./component/MwTableCameraLog";
import SearchTable from "./component/SearchCamera.vue";
import MwDialog from "@/components/Dialog";
import { ElMessage, ElMessageBox } from 'element-plus';
import FlvVideo from "@/components/flvVideo";
import { downloadFile } from '@/utils';

import { CirclePlus, VideoPlay } from '@element-plus/icons-vue';
import { ref, reactive, getCurrentInstance, onMounted, watch, nextTick } from "vue";

import { globalStore } from "@/store/global";
const globalVue = globalStore();

const instance = getCurrentInstance();
const _this = instance.appContext.config.globalProperties; //vue3获取当前this
const storage = _this.$utils.storage;

// 生命周期
onMounted(() => {
  getTableData();
  getSelect();
});

let getTableData = () => {
  // 查询摄像头
  let paramsCamera = {
    ...pagination,
    ...searchForm
  };
  searchForm['city'] && (paramsCamera['city'] = searchForm['city'] + '');
  tablLoading.value = true;
  instance.proxy.$http.get('overview.getCameraList', { params: paramsCamera }).then(res => {
    let { content, totalElements } = res.data;
    tableData.value = content;
    pagination.total = totalElements;
    tablLoading.value = false;
  }).catch(err => tablLoading.value = false);
};


let getSelect = async () => {
  instance.proxy.$http.get('overview.version', {
    params: {
      page: 1,
      size: 9999,
    }
  }).then(res => {
    let { content, totalElements } = res.data;
    selectOTA.value = content.map(i => {
      i['label'] = `${i.name} (${i.version})`;
      i['value'] = i.id;
      i['key'] = i.id;
      return i;
    });
  });
  
  selectClassification.value = await globalVue.getSelect('classificationSelect');


  instance.proxy.$http.get('archiveData.dictDetail', { params: { name: 'camera_type' } }).then(res => {
    selectState.value = res.data;
  });
  instance.proxy.$http.get('archiveData.dictDetail', { params: { name: 'camera_status' } }).then(res => {
    selectStatus.value = res.data;
  });
  instance.proxy.$http.get('archiveData.dictDetail', { params: { name: 'camera_pixel' } }).then(res => {
    selectPixel.value = res.data;
  });
  instance.proxy.$http.get('archiveData.dictDetail', { params: { name: 'camera_ratio' } }).then(res => {
    selectRatio.value = res.data;
  });
  instance.proxy.$http.get('archiveData.dictDetail', { params: { name: 'camera_algorithm' } }).then(res => {
    selectAlgorithm.value = res.data;
  });
  instance.proxy.$http.get('archiveData.getAmbulanceTreeSelect').then(res => {
    treeVehicleSelect.value = formatTree(res.data, 1)
  });
  instance.proxy.$http.get('archiveData.getHospitalSelect').then(res => {
    selectHospital.value = res.data.map(i => {
      i['label'] = i.selectName;
      i['value'] = i.id;
      i['key'] = i.id;
      return i;
    });
  });
  instance.proxy.$http.get('archiveData.getDeviceSelect').then(res => {
    selectCamera.value = res.data.map(i => {
      i['label'] = i.name;
      i['value'] = i.deviceId;
      i['key'] = i.deviceId;
      return i;
    });
  });
  instance.proxy.$http.get('archiveData.getCitySelect').then(res => {
    selectCity.value = res.data.map(i => {
      i['label'] = i.selectName;
      i['value'] = i.id;
      return i;
    });
  });
};

function formatTree(treeData, zoom) {
  let treeArr = []
  treeData.forEach(i => {
    let item = {}
    item.label = i.name;
    item.zoom = zoom;
    item.value = i.id || i.type;
    if (i.city) {
      item.city = i.city
      item.type = i.type
    }
    i.list && (item.children = formatTree(i.list, zoom + 1))
    i.cameraTreeDtoList && (item.children = formatTree(i.cameraTreeDtoList, zoom + 1))
    if (item.children && item.children.length) {
      item.disabled = false;
    }else{
      item.disabled = item.zoom != 3;
    }
    
    treeArr.push(item)
  })
  return treeArr
}
// 下拉数据
const selectCity = ref([]);   // 城市
const selectHospital = ref([]);   // 医院
const treeVehicleSelect = ref([]);   // 救护车

const selectCamera = ref([]);   // 摄像头
const selectOTA = ref([]);   // OTA package
const selectState = ref([]);   // state
const selectPixel = ref([]);   // Pixel
const selectRatio = ref([]);   // Resolution Ratio
const selectAlgorithm = ref([]);   // Association Algorithm
const selectStatus = ref([]);   // Status
const selectClassification = ref([]);  



// 弹框数据
let rtmp_disabled = ref(false);
let dialogShow = ref(false);
let propsCascader = {expandTrigger: 'hover'}
let dialogTitle = ref(' Camera');
let dialogState = ref('Add'); //  Add Edit Detail 三种状态 根据状态来判断提交方法
let dialogRef = ref(null);
let dialogFrom = reactive({
  position: 'rear',
  obsurl: `{
    ak: '',
    sk: '',
    endPoint: '',
    bucketName: '',
  }`
});
let checkRTMPurl = (rule, value, callback) => {
  let url = value.split(/\:(\d{4})/g).at(-1);
  if (url.match(/\//igm).length == 2) {
    return callback();
  };
  callback(new Error('The rtmp format does not meet the requirements and needs to be rtmp://ip:1935/aaa/bb Format of'))
};
let dialogRules = reactive({
  serialnumber: [
    { required: true, message: 'Please input Camera ID', trigger: 'blur' },
    { pattern: /^[^\s]+(\s+[^\s]+)*$/, message: 'String cannot contain spaces', trigger: 'blur' },
  ],
  // ip: [
  //   { required: true, message: 'Please input IP', trigger: 'blur' },
  //   { pattern: /^((2((5[0-5])|([0-4]\d)))|([0-1]?\d{1,2}))(\.((2((5[0-5])|([0-4]\d)))|([0-1]?\d{1,2}))){3}$/,    //正则ip
  //           message: "Please enter the correct IP address", trigger: "change"}
  // ],
  rtmpurl: [
    { required: true, message: 'Please input RTMP Stream Address', trigger: 'blur' },
    { pattern: /^[^\s]+(\s+[^\s]+)*$/, message: 'String cannot contain spaces', trigger: 'blur' },
    // { validator: checkRTMPurl, trigger: 'blur' },
  ],
  obsurl: [
    { required: true, message: 'Please input OBS Address', trigger: 'blur' },
  ],
  name: [
    { required: true, message: 'Please input Name', trigger: 'blur' },
    { pattern: /^[^\s]+(\s+[^\s]+)*$/, message: 'String cannot contain spaces', trigger: 'blur' },
  ],
});
let dialogSubmit = async () => {
  dialogFrom['ambulanceId'] = dialogFrom?.ambulanceId?.at(-1) || null;
  let formEl = dialogRef.value;
  if (!formEl) return;
  await formEl.validate((valid, fields) => {
    if (valid) {
      dialogFrom['algorithm'] = dialogFrom['algorithm'] ? dialogFrom['algorithm'] + '' : '';
      let url = dialogState.value == 'Add' ? 'archiveData.insertCamera' : 'archiveData.updateCamera';
      if (dialogState.value == 'Add') {
        dialogFrom['topic'] = `DDPTm/${dialogFrom.serialnumber}/S/T`;
        dialogFrom['serverTopic'] = `DDPTm/${dialogFrom.serialnumber}/C/T`;
        instance.proxy.$http.post(url, dialogFrom).then(res => {
          if (res.success) {
            onSearch();
            dialogClose();
          };
        });
      } else {
        instance.proxy.$http.put(url, dialogFrom).then(res => {
          if (res.success) {
            onSearch();
            dialogClose();
          };
        });
      };
    } else {
      console.error('error submit!', valid, fields, dialogFrom);
    };
  });
};
let dialogClose = () => {
  dialogShow.value = false;
  dialogRef.value.resetFields();
  for (let item in dialogFrom) {
    if (dialogFrom[item] instanceof Array) {
      dialogFrom[item] = [];
    } else {
      dialogFrom[item] = '';
    };
  };
  dialogFrom['position'] = 'rear';
  dialogFrom['obsurl'] = `{
    ak: '',
    sk: '',
    endPoint: '',
    bucketName: '',
  }`;
};

function openDialog(state) {
  dialogState.value = state;
  dialogShow.value = true;
  rtmp_disabled.value = false;
  for (let item in dialogFrom) {
    delete dialogFrom[item];
  };
  dialogFrom['position'] = 'rear';
  dialogFrom['obsurl'] = `{
    "ak": "",
    "sk": "",
    "endPoint": "",
    "bucketName": "",
  }`;
};

// 表格数据
const tableData = ref([]);
const tablLoading = ref(false);
const pagination = reactive({
  page: 1,
  size: 10,
  total: 0
});
const searchForm = reactive({});
// 推流弹框
const plugFlow = ref(false);
const plugVideoFlow = ref(false);
const videoRef = ref(null);
const rowData = ref({});

const player = ref(null);
const videoUrl = ref('');
const hlsVideo = ref(null);

function onSearch() {
  getTableData();
};

function rtmpToHttp(url, type) {
  let str;
  switch (type) {
    case 'm3u8':
      str = url.replace('rtmp://', 'http://') + '/hls.m3u8';
      break;
    default:
      break;
  };
  return str.replace(':1935/', ':8099/');
};

function palyVideo(row) {
  rowData.value = row;
  plugFlow.value = true;
  if (row.status == '1') {
    plugVideoFlow.value = true;
  }else{
    plugVideoFlow.value = false;
  }
  instance.proxy.$http.get('overview.getVideo', { params: { cameraId: row.id } }).then(res => {
    let url;
    if (res.data[0]?.rtmpurl.indexOf('rtmp://') > -1) {
      url = rtmpToHttp(res.data[0]?.rtmpurl, 'm3u8');
    }else{
      url = res.data[0]?.rtmpurl
    }
    let uuid = _this.$utils.createHash(18);
    let videoFlow = {
      "uuid": uuid,
      "cameraVideoList": res.data
    };
    videoUrl.value = url;
    storage.setLocal('videoFlow', videoFlow);
    url && instance.proxy.$http.post('overview.openVideoStream', videoFlow).then(res => { });
    nextTick(() => {
      url && initVideoPlayer(url, videoRef.value);
    });
  });
};
function cliseVideo() {
  plugFlow.value = false;
  if (plugVideoFlow.value) {
    hlsVideo.value.disposeVideo();
    // 关闭推流
    let videoFlow = storage.getLocal('videoFlow');
    storage.removeLocal('videoFlow');
    instance.proxy.$http.post('overview.closeVideoStream', videoFlow).then(res => { });
    plugVideoFlow.value = false;
  }
};
let initVideoPlayer = (url, dom) => {
  // 第一个选中的要播放的video标签, 记得是video标签, 
  player.value = _this.$video(dom, {
    autoplay: true, // 是否自动播放
    controls: true, // 是否显示控件
    width: 600,
    height: 400
  });

  player.value.src({
    src: url,
    //  rtmp/flv       application/x-mpegURL
    type: 'application/x-mpegURL', // 这个type值必写, 告诉videojs这是一个rtmp流视频
  });
};

function paginationChange(pagination) {
  onSearch();
};

function onEdit(row) {
  openDialog('Edit');
  for (let i in row) {
    if (i == 'algorithm') {
      dialogFrom['algorithm'] = row[i] && row[i].split(",");
    }else if (i == 'ambulanceId') {
      dialogFrom[i] = formatAmbulanceId(treeVehicleSelect.value, row[i])
    }else{
      dialogFrom[i] = row[i];
    }
  };
};

function formatAmbulanceId(treeData, id) {
  let arr = [];
  treeData.forEach(i => {
    i.children.forEach(x => {
      x.children.forEach(y => {
        if (y.value == id) {
          arr = [i.value, x.value, y.value]
        }
      })
    })
  })
  return arr
}

function onRefresh() {
  for (let item in searchForm) {
    delete searchForm[item];
  };
  getTableData();
};

function onDelete(row) {
  ElMessageBox.confirm(
    'Delete Camera ？',
    'Delete',
    {
      confirmButtonText: 'Confirm',
      cancelButtonText: 'Cancel'
    }
  )
    .then(() => {
      instance.proxy.$http.delete('archiveData.deleteCamera', { data: { id: row.id + '' } }).then(res => {
        onSearch();
        ElMessage({
          type: 'success',
          message: 'Delete Camera successfully',
        });
      });
    })
    .catch(() => { });
};

function serialChange(val) {
  let position = dialogFrom['position'];
  dialogFrom['rtmpurl'] = `rtmp://172.30.30.145:1935/${val}/${position}`;
};
function positionChange(val) {
  let str = dialogFrom['rtmpurl'];
  let beforeIndex = str.lastIndexOf('/');
  let replaceStr = str.substr(beforeIndex);
  dialogFrom['rtmpurl'] = str.replace(replaceStr, ('/' + val));
};

function onUpload(row) {
  dialogFrom2.cameraList = [row.id];
  dialogShow2.value = true;
}
function onLog(row) {
  dialogRow3.value = row;
  dialogShow3.value = true;
  searchFormDialog.deviceId = row.serialnumber;
  getLogList();
};

// ============================ 弹框2 ================================

let dialogShow2 = ref(false);
let dialogFrom2 = reactive({});
let dialogSubmit2 = async () => {
  if (!dialogFrom2?.versionId) {
    ElMessage({
      type: 'error',
      message: 'Please Select',
    });
    return;
  };
  ElMessageBox.confirm(
    'Confirm Upgrade Camera？',
    'Upgrade Camera',
    {
      confirmButtonText: 'Confirm',
      cancelButtonText: 'Cancel'
    }).then(() => {
      instance.proxy.$http.post('overview.versionUpgrade', dialogFrom2).then(res => {
        if (res.success) {
          ElMessage({
            type: 'success',
            message: 'Upgrade message sent',
          });
          onSearch();
          dialogClose2();
        };
      });
    })
    .catch(() => { });
};
let dialogClose2 = () => {
  dialogShow2.value = false;
  dialogFrom2.versionId = '';
};
const filterMethod = (query, item) => item.label.toLowerCase().includes(query.toLowerCase());


// ============================ 弹框3 ================================

// 弹框表格数据
const tableDataDialog = ref([]);
const tablLoadingDialog = ref(false);
const paginationDialog = reactive({
  page: 1,
  size: 10,
  total: 0
});
const searchFormDialog = reactive({})
const sendTxt = ref('Send');
const sendNum = ref(60);
const sendDisabled = ref(false);
let timer = null;


function getLogList() {
  let param = {
    deviceId: dialogRow3.value.serialnumber,
    ...paginationDialog,
    ...searchFormDialog
  };
  tablLoadingDialog.value = true;
  instance.proxy.$http.get('archiveData.getLogList', { params: param }).then(res => {
    let { content, totalElements } = res.data;
    tableDataDialog.value = content;
    paginationDialog.total = totalElements;
    tablLoadingDialog.value = false;
  }).catch(() => tablLoadingDialog.value = false);
};

function getLogPost() {
  sendDisabled.value = true;
  sendTxt.value = `Send (${sendNum.value} seconds)`;
  let params = {
    deviceList: [{id: dialogRow3.value.id, deviceId: dialogRow3.value.serialnumber}],
    startTime: null,
    endTime: null,
  };

  instance.proxy.$http.post('archiveData.getLog', params).then(res => {
    if (res.success) {
      ElMessage({
        type: 'success',
        message: 'Message has been sent',
      });
      timer = setInterval(() => {
        if (sendNum.value == 0) {
          clearInterval(timer);
          sendTxt.value = 'Send';
          sendNum.value = 60;
          sendDisabled.value = false;
        } else {
          sendNum.value--;
          sendTxt.value = `Send (${sendNum.value} seconds)`;
        };
      }, 1000);
    }else{
      clearInterval(timer);
      sendTxt.value = 'Send';
      sendNum.value = 60;
      sendDisabled.value = false;
    }
  });
};

let dialogShow3 = ref(false);
let dialogRow3 = ref(null);
let dialogClose3 = () => {
  dialogShow3.value = false;
  clearInterval(timer);
  sendTxt.value = 'Send';
  sendNum.value = 60;
  sendDisabled.value = false;
};
function download(row) {
  let obj = {
    url: window.global_API.prodUrl + "file/log" + row.fileurl,
    ...row
  };
  downloadFile(obj, row.filename);
  // window.location.href = row.fileurl;
};
function deleteLog(row) {
  ElMessageBox.confirm(
    'Delete Log ？',
    'Delete',
    {
      confirmButtonText: 'Confirm',
      cancelButtonText: 'Cancel'
    }
  )
    .then(() => {
      instance.proxy.$http.delete('archiveData.deleteLog', { params: { deviceId: dialogRow3.value.serialnumber + '', filename: row.filename } }).then(res => {
        getLogList();
        ElMessage({
          type: 'success',
          message: 'Delete filename successfully',
        });
      });
    })
    .catch(() => { });
};
</script>
<template>
  <div class="table_index">
    <SearchTable :searchForm="searchForm" :selectHospital="selectHospital" :selectClassification="selectClassification" :selectState="selectStatus" :selectCity="selectCity" :selectAlgorithm="selectAlgorithm" @onSearch="onSearch" @onRefresh="onSearch" @addEquipment="openDialog('Add')" />
    <div class="table_content">
      <MwTable v-loading="tablLoading" :data="tableData" :pagination="pagination" @paginationChange="paginationChange" @operate1="palyVideo" @operate2="onEdit" @operate3="onUpload" @operate4="onLog" @operate5="onDelete"></MwTable>
    </div>
  </div>

  <el-dialog v-model.sync="plugFlow" title="Camera" @close="cliseVideo" width="725px" draggable>
    <div class="form_item">
      <div>Camera ID：{{ rowData.serialnumber }}</div>
      <div>Name：{{ rowData.name }}</div>
    </div>
    <div class="form_item">
      <div>Algorithm：{{ rowData.algorithmName }}</div>
    </div>
    <div style="width: 100%;height: 400px;" v-if="plugFlow && plugVideoFlow">
      <FlvVideo ref="hlsVideo" :src="videoUrl"></FlvVideo>
    </div>
    <div v-else class="no_video">
      <img src="@/assets/image/index/ico_offline.png" alt="">
    </div>
  </el-dialog>

  <mw-dialog :show="dialogShow3" title="View Log" width="80%" @close="dialogClose3" :footerShow="false">
    <el-form :inline="true" :model="searchFormDialog" class="form_search_table">
      <!-- <el-form-item label="Time">
        <el-date-picker
          v-model="searchFormDialog.date"
          value-format="YYYY-MM-DD HH:mm:ss"
          type="datetimerange"
          range-separator="To"
          start-placeholder="Start date"
          end-placeholder="End date"
          clearable
        />
      </el-form-item> -->
      <el-form-item label="Camera">
        <el-select v-model="searchFormDialog.deviceId" placeholder="Please select" filterable clearable>
          <el-option v-for="item in selectCamera" :key="item.id" :label="item.label" :value="item.value" />
        </el-select>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" @click="getLogList">Query</el-button>
        <el-button type="primary" @click="getLogPost" :disabled="sendDisabled">{{ sendTxt }}</el-button>
      </el-form-item>
    </el-form>
    <div class="table_content">
      <MwTableLog v-loading="tablLoadingDialog" :data="tableDataDialog" :pagination="paginationDialog" @paginationChange="getLogList" @operate1="download" @operate2="deleteLog" />
    </div>
  </mw-dialog>

  <mw-dialog :show="dialogShow2" :title="'Upgrade Camera'" @submit="dialogSubmit2" @close="dialogClose2">
    <div class="dialogShow2_select">
      <span>OTA Package </span>
      <el-select class="select_mw" v-model="dialogFrom2.versionId" placeholder="Please select" filterable clearable>
        <el-option v-for="item in selectOTA" :key="item.id" :label="item.label" :value="item.value" />
      </el-select>
    </div>
  </mw-dialog>

  <mw-dialog :show="dialogShow" :title="dialogState + dialogTitle" width="920px" @submit="dialogSubmit" @close="dialogClose">
    <el-form ref="dialogRef" class="dialog_form" :inline="true" :model="dialogFrom" label-width="170px" :rules="dialogRules">
      <el-form-item label="Camera ID" prop="serialnumber">
        <el-input v-model="dialogFrom.serialnumber" @input="serialChange" class="value_input" placeholder="Enter" clearable />
      </el-form-item>
      <el-form-item label="Camera Name" prop="name">
        <el-input v-model="dialogFrom.name" class="value_input" placeholder="Enter" clearable />
      </el-form-item>
      <el-form-item label="Bind Vehicle">
        <el-cascader 
          clearable 
          filterable
          class="value_input"
          :show-all-levels="false"
          :props="propsCascader"
          v-model="dialogFrom.ambulanceId" 
          :options="treeVehicleSelect" />
        <!-- <el-select class="value_input" v-model="dialogFrom.ambulanceId" placeholder="Please select" filterable clearable>
          <el-option v-for="item in selectVehicle" :key="item.id" :label="item.label" :value="item.value" />
        </el-select> -->
      </el-form-item>
      <el-form-item label="Model">
        <el-input v-model="dialogFrom.model" class="value_input" placeholder="Enter" clearable />
      </el-form-item>
      <el-form-item label="Device Type">
        <el-select class="value_input" v-model="dialogFrom.devicetype" placeholder="Please select" filterable clearable>
          <el-option v-for="item in selectState" :key="item.id" :label="item.label" :value="item.value" />
        </el-select>
      </el-form-item>
      <el-form-item label="Resolution Ratio">
        <el-select class="value_input" v-model="dialogFrom.resolutionrate" placeholder="Please select" filterable clearable>
          <el-option v-for="item in selectRatio" :key="item.id" :label="item.label" :value="item.value" />
        </el-select>
      </el-form-item>
      <el-form-item label="Pixel">
        <el-select class="value_input" v-model="dialogFrom.pixel" placeholder="Please select" filterable clearable>
          <el-option v-for="item in selectPixel" :key="item.id" :label="item.label" :value="item.value" />
        </el-select>
      </el-form-item>
      <el-form-item label="Algorithm">
        <el-select class="value_input" v-model="dialogFrom.algorithm" placeholder="Please select" multiple collapse-tags collapse-tags-tooltip filterable clearable>
          <el-option v-for="item in selectAlgorithm" :key="item.id" :label="item.label" :value="item.value" />
        </el-select>
      </el-form-item>
      <el-form-item label="RTMP Stream Address" prop="rtmpurl">
        <div class="rtmp_box">
          <el-input v-model="dialogFrom.rtmpurl" class="value_input" :disabled="!rtmp_disabled" :rows="8" type="textarea" placeholder="Enter" clearable />
          <div class="disabled_box">
            <span>Edit：</span>
            <el-switch v-model="rtmp_disabled" />
          </div>
        </div>
      </el-form-item>
      <el-form-item label="OBS Address" prop="obsurl">
        <el-input v-model="dialogFrom.obsurl" :rows="8" type="textarea" class="value_input" placeholder="Enter" clearable />
      </el-form-item>
      <!-- <el-form-item label="IP" prop="ip">
        <el-input v-model="dialogFrom.ip" class="value_input"  placeholder="Enter" clearable />
      </el-form-item> -->
      <el-form-item label="Position">
        <el-select class="value_input" v-model="dialogFrom.position" placeholder="Please select" @change="positionChange" filterable>
          <el-option label="Front" value="front" />
          <el-option label="Rear" value="rear" />
        </el-select>
      </el-form-item>
    </el-form>
  </mw-dialog>
</template>

<style lang="less" scoped>
.rtmp_box{
  position: relative;
  .disabled_box{
    display: flex;
    flex-flow: row;
    align-items: center;
    position: absolute;
    left: -90px;
    top: 30px;
  }
}
.dialogShow2_select {
  display: flex;
  align-items: center;

  span {
    display: block;
    margin-right: 10px;
  }

  .select_mw {
    flex: 1;
  }
}

</style>